<?php

namespace App\Http\Controllers\Api;

use App\Http\Requests\Api\OrdersRequest;
use App\Jobs\CloseOrder;

use App\Models\LogBalance;
use App\Models\Order;
use App\Models\Product;
use App\Models\Schedule;
use App\Models\User;
use App\Transformers\OrderTransformer;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;

class OrdersController extends Controller
{
    /**
     * 订单列表
     *
     * @param OrdersRequest $request
     * @return \Dingo\Api\Http\Response
     */
    public function index(OrdersRequest $request)
    {
        $where = $request->only(['status', 'refund_status']);

        if ($this->user->role == User::CUSTOMER) {
            $belongs['user_id'] = $this->user->id;
        } else {
            $belongs['shop_id'] = $this->user->shop->id;
        }

        $data = Order::where(function ($query) use ($where, $belongs) {
            $query->where($belongs);

            if (in_array('cancel', $where)) {
                $query->whereIn('status', [Order::STATUS_USER_CANCEL, Order::STATUS_SELLER_CANCEL, Order::STATUS_BOTH_CANCEL]);
                $query->orWhere('closed', true);
            } elseif (in_array('processing', $where)) {
                $query->whereIn('status', [Order::STATUS_RECEIVED, Order::STATUS_SIGNED, Order::STATUS_CONFIRM]);
            } else if ($this->user->role == User::CUSTOMER && in_array('paid', $where)) {
                $query->whereIn('status', [Order::STATUS_PAID, Order::STATUS_RECEIVED, Order::STATUS_SIGNED]);
            } else {
                $query->where('closed', false)->where($where);
            }

            if ($this->user->role == User::SELLER) {
                $query->whereNotNull('paid_at');
                $query->where('paid_at', '<=', date('Y-m-d H:i:s', time() - Order::SELLER_VIEW_ORDER_STANDARD));#商家600秒后才能看到订单
            }
        })->paginate();

        return $this->response->paginator($data, new OrderTransformer([
            'id', 'title', 'shop_name', 'status', 'refund_status', 'user_avatar', 'contact_name', 'contact_phone', 'scheduled_time', 'closed', 'paid_at', 'total_amount', 'image',
        ]));
    }

    /**
     * 订单详情
     *
     * @param $id
     * @return \Dingo\Api\Http\Response
     * @throws \Illuminate\Auth\Access\AuthorizationException
     */
    public function show($id)
    {
        if ($this->user->role == User::CUSTOMER) {
            $belongs['user_id'] = $this->user->id;
        } else {
            $belongs['shop_id'] = $this->user->shop->id;
        }

        $order = Order::where(function ($query) use ($belongs) {
            $query->where($belongs);

            if ($this->user->role == User::SELLER) {
                $query->whereNotNull('paid_at');
                $query->where('paid_at', '<=', date('Y-m-d H:i:s', time() - Order::SELLER_VIEW_ORDER_STANDARD));#商家600秒后才能看到订单
            }
        })->where('id', $id)->first();

        //判断用户是否有查看该订单的权限
        if ($this->user->role == User::CUSTOMER) {
            $this->authorize('view', $order);
        } else {
            $this->authorize('seller_view', $order);
        }

        if (!$order) {
            $this->response->error(trans('api.not_exists'), 200);
        }

        return $this->response->item($order, new OrderTransformer());
    }

    /**
     * 用户提交订单
     *
     * @param OrdersRequest $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function create(OrdersRequest $request)
    {
        $data = $request->only(['contact_name', 'contact_phone', 'goods_id', 'schedule_id']);

        $data['goods_type'] = 'App\Models\Product';

        $goods = new $data['goods_type']();

        $goods_data = $goods->where('id', $data['goods_id'])->select('id', 'shop_id')->first();

        $schedule = Schedule::find($data['schedule_id']);

        $data['shop_id'] = $goods_data->shop_id;

        $data['total_amount'] = $schedule->price;

        $data['user_id'] = $this->user->id;

        //判断时间是否属于该商品
        if (!in_array($data['schedule_id'], $goods_data->schedules->pluck('id')->toArray())) {
            $this->response->error(trans('api.save_failed') . ' ' . trans('api.schedule_is_invalid'), '200');
        }

        //创建订单
        $order = DB::transaction(function () use ($data) {
            try {
                $order = Order::create($data);

                $job = (new CloseOrder($order))
                    ->delay(Carbon::now()->addSeconds(Order::CLOSE_SECONDS));

                dispatch($job);

                return $order;

            } catch ( \Exception $exception ) {
                $this->response->error(trans('api.save_failed'), '200');
            }
        });

        return response()->json(['message' => trans('api.save_succeed'), 'code' => 1, 'status' => true, 'data' => $order], 200);
    }

    /**
     * 用户支付订单
     *
     * @param OrdersRequest $request
     * @return \Illuminate\Http\JsonResponse
     * @throws \Illuminate\Auth\Access\AuthorizationException
     */
    public function pay(OrdersRequest $request)
    {
        $id = $request->get('id');

        $pay_password = $request->get('pay_password');

        $order = Order::where('id', $id)->first();

        $this->authorize('update', $order);#判断用户是否有修改该订单的权限

        //判断是否设置支付密码
        if (!$this->user->wallet->pay_password) {
            return response(['message' => trans('api.no_pay_password_set'), 'code' => 4, 'status' => false]);
        }

        //判断密码是否正确
        if (!Hash::check($pay_password, $this->user->wallet->pay_password)) {
            return response(['message' => trans('api.pay_password_error'), 'code' => 0, 'status' => false]);
        }

        //判断订单是否关闭
        if ($order->closed) {
            $this->response->error(trans('api.order_closed'), 200);
        }

        //判断订单是否能支付
        if ($order->status != Order::STATUS_PENDING || $order->paid_at) {
            $this->response->error(trans('api.save_failed') . ',' . trans('api.order_status') . ':' . $order->status, 200);
        }

        //判断余额是否足够
        if ($this->user->wallet->balance < $order->total_amount) {
            return response()->json(['message' => trans('api.pay_failed') . ',' . trans('api.balance_not_enough'), 'code' => 2, 'status' => false], 200);
        }

        //判断该订单时间是否被占用
        if ($order->schedule->status) {
            return response()->json(['message' => trans('api.pay_failed') . ',' . trans('api.schedule_is_occupied'), 'code' => 3, 'status' => false], 200);
        }

        //订单状态修改为已付款 并扣钱
        DB::transaction(function () use ($id, $order) {
            try {
                $order->fill([
                    'paid_at' => Carbon::now(),
                    'status' => Order::STATUS_PAID,
                ])->save();

                $order->schedule->status = 1;

                $order->schedule->save();

                $this->user->wallet->balance -= getMoneyFormat($order->total_amount);

                $this->user->push();

            } catch ( \Exception $exception ) {
                $this->response->error(trans('api.pay_failed'), '200');
            }
        });

        return response()->json(['message' => trans('api.pay_succeed'), 'code' => 1, 'status' => true, 'data' => ''], 200);
    }

    /**
     * 商家接单
     *
     * @param OrdersRequest $request
     * @return \Illuminate\Http\JsonResponse
     * @throws \Illuminate\Auth\Access\AuthorizationException
     */
    public function receive(OrdersRequest $request)
    {
        $id = $request->get('id');

        $order = Order::where('id', $id)->first();

        $this->authorize('seller_update', $order);#判断用户是否有修改该订单的权限

        //判断订单是否关闭
        if ($order->closed) {
            $this->response->error(trans('api.order_closed'), 200);
        }

        //判断订单是否支付
        if ($order->status != Order::STATUS_PAID || !$order->paid_at) {
            $this->response->error(trans('api.save_failed') . ',' . trans('api.order_status') . ':' . $order->status, 200);
        }

        //判断订单是否已经申请退款
        if ($order->refund_status != Order::REFUND_STATUS_PENDING) {
            $this->response->error(trans('api.save_failed') . ',' . trans('api.order_status') . ':' . $order->refund_status, 200);
        }

        $order->status = Order::STATUS_RECEIVED;

        $res = $order->save();

        if ($res) {
            return response()->json(['message' => trans('api.save_succeed'), 'code' => 1, 'status' => true, 'data' => ''], 200);
        } else {
            return response()->json(['message' => trans('api.save_failed'), 'code' => 0, 'status' => false], 200);
        }
    }

    /**
     * 用户确认订单 签到
     *
     * @param OrdersRequest $request
     * @return \Illuminate\Http\JsonResponse
     * @throws \Illuminate\Auth\Access\AuthorizationException
     */
    public function signed(OrdersRequest $request)
    {
        $id = $request->get('id');

        $order = Order::where('id', $id)->first();

        $this->authorize('update', $order);#判断用户是否有修改该订单的权限

        //判断订单是否关闭
        if ($order->closed) {
            $this->response->error(trans('api.order_closed'), 200);
        }

        //判断订单是否支付 且商家是否接单
        if ($order->status != Order::STATUS_RECEIVED || !$order->paid_at) {
            $this->response->error(trans('api.save_failed') . ',' . trans('api.order_status') . ':' . $order->status, 200);
        }

        //判断用户距离
        if ($order->user_distance > Order::DISTANCE_STANDARD) {
            return response()->json(['message' => trans('api.distance_not_enough'), 'code' => 2, 'status' => false], 200);
        }

        $order->status = Order::STATUS_SIGNED;

        $res = $order->save();

        if ($res) {
            return response()->json(['message' => trans('api.save_succeed'), 'code' => 1, 'status' => true, 'data' => ''], 200);
        } else {
            return response()->json(['message' => trans('api.save_failed'), 'code' => 0, 'status' => false], 200);
        }
    }

    public function confirm(OrdersRequest $request)
    {
        $id = $request->get('id');

        $order = Order::where('id', $id)->first();

        $this->authorize('update', $order);#判断用户是否有修改该订单的权限

        //判断订单是否关闭
        if ($order->closed) {
            $this->response->error(trans('api.order_closed'), 200);
        }

        //判断订单是否支付 且商家是否接单 且用户是否签到
        if ($order->status != Order::STATUS_SIGNED || !$order->paid_at) {
            $this->response->error(trans('api.save_failed') . ',' . trans('api.order_status') . ':' . $order->status, 200);
        }

        //判断用户距离
        if ($order->user_distance > Order::DISTANCE_STANDARD) {
            return response()->json(['message' => trans('api.distance_not_enough'), 'code' => 2, 'status' => false], 200);
        }

        $order->status = Order::STATUS_CONFIRM;

        $res = $order->save();

        if ($res) {
            return response()->json(['message' => trans('api.save_succeed'), 'code' => 1, 'status' => true, 'data' => ''], 200);
        } else {
            return response()->json(['message' => trans('api.save_failed'), 'code' => 0, 'status' => false], 200);
        }
    }

    /**
     * 商家完成订单
     *
     * @param OrdersRequest $request
     * @return \Illuminate\Http\JsonResponse
     * @throws \Illuminate\Auth\Access\AuthorizationException
     */
    public function finish(OrdersRequest $request)
    {
        $id = $request->get('id');

        $order = Order::where('id', $id)->first();

        $this->authorize('seller_update', $order);#判断用户是否有修改该订单的权限

        //判断订单是否关闭
        if ($order->closed) {
            $this->response->error(trans('api.order_closed'), 200);
        }

        //判断订单是否能完成
        if ($order->status != Order::STATUS_CONFIRM || !$order->paid_at) {
            $this->response->error(trans('api.save_failed') . ',' . trans('api.order_status') . ':' . $order->status, 200);
        }

        //判断订单是否申请退款
        if ($order->refund_status != Order::REFUND_STATUS_PENDING) {
            $this->response->error(trans('api.save_failed') . ',' . trans('api.order_status') . ':' . $order->refund_status, 200);
        }

        //判断用户距离是否足以完成服务
        if ($order->user_distance > Order::DISTANCE_STANDARD) {
            return response()->json(['message' => trans('api.distance_not_enough'), 'code' => 2, 'status' => false], 200);
        }

        DB::transaction(function () use ($order) {
            try {
                $order->status = Order::STATUS_FINISH;

                $order->save();

                //收取订单金额
                $this->user->wallet->balance += getMoneyFormat($order->total_amount * Order::REWARD_DISCOUNT);

                $this->user->push();

            } catch ( \Exception $exception ) {
                $this->response->error(trans('api.save_failed'), '200');
            }
        });

        return response()->json(['message' => trans('api.save_succeed'), 'code' => 1, 'status' => true, 'data' => ''], 200);
    }

    /**
     * 用户取消订单
     *
     * @param OrdersRequest $request
     * @return \Illuminate\Http\JsonResponse
     * @throws \Illuminate\Auth\Access\AuthorizationException
     */
    public function userCancel(OrdersRequest $request)
    {

        $id = $request->get('id');

        $order = Order::where('id', $id)->first();

        $this->authorize('update', $order);#判断用户是否有修改该订单的权限

        //判断订单是否能取消
        if ($order->status != Order::STATUS_PENDING && $order->status != Order::STATUS_PAID && $order->status != Order::STATUS_SELLER_CANCEL) {
            $this->response->error(trans('api.save_failed') . ',' . trans('api.order_status') . ':' . $order->status, 200);
        }

        if ($order->status == Order::STATUS_PAID && $order->paid_at) {
            $order->refund_status = Order::REFUND_STATUS_APPLIED;#申请退款
        }

        DB::transaction(function () use ($order) {
            try {

                if ($order->status == Order::STATUS_SELLER_CANCEL) {
                    $order->status = Order::STATUS_BOTH_CANCEL;
                } else {
                    $order->status = Order::STATUS_USER_CANCEL;
                }

                $order->save();

                $order->schedule->status = 0;

                $order->schedule->save();

            } catch ( \Exception $exception ) {
                $this->response->error(trans('api.save_failed'), '200');
            }
        });

        return response()->json(['message' => trans('api.cancel_succeed'), 'code' => 1, 'status' => true, 'data' => ''], 200);
    }

    /**
     * 商家取消订单
     *
     * @param OrdersRequest $request
     * @return \Illuminate\Http\JsonResponse
     * @throws \Illuminate\Auth\Access\AuthorizationException
     */
    public function sellerCancel(OrdersRequest $request)
    {
        $id = $request->get('id');

        $order = Order::where('id', $id)->first();

        $this->authorize('seller_update', $order);#判断用户是否有修改该订单的权限

        //判断订单是否能取消
        if ($order->status != Order::STATUS_PENDING && $order->status != Order::STATUS_PAID && $order->status != Order::STATUS_USER_CANCEL) {
            $this->response->error(trans('api.save_failed') . ',' . trans('api.order_status') . ':' . $order->status, 200);
        }

        if ($order->status == Order::STATUS_PAID && $order->paid_at) {
            $order->refund_status = Order::REFUND_STATUS_APPLIED;#申请退款
        }

        if ($order->status == Order::STATUS_USER_CANCEL) {
            $order->status = Order::STATUS_BOTH_CANCEL;
        } else {
            $order->status = Order::STATUS_SELLER_CANCEL;
        }

        $res = $order->save();

        if ($res) {
            return response()->json(['message' => trans('api.cancel_succeed'), 'code' => 1, 'status' => true, 'data' => ''], 200);
        } else {
            return response()->json(['message' => trans('api.cancel_failed'), 'code' => 0, 'status' => false], 200);
        }
    }

    /**
     * 退款验证
     *
     * @param OrdersRequest $request
     * @return \Illuminate\Http\JsonResponse
     * @throws \Illuminate\Auth\Access\AuthorizationException
     */
    public function refundVerify(OrdersRequest $request)
    {
        $id = $request->get('id');

        $order = Order::where('id', $id)->first();

        $this->authorize('update', $order);#判断用户是否有修改该订单的权限

        //判断订单是否关闭
        if ($order->closed) {
            $this->response->error(trans('api.order_closed'), 200);
        }

        //判断订单是否验证
        if ($order->refund_verify) {
            $this->response->error(trans('api.verified'), '200');
        }

        //...验证
        $verify_code = $request->get('verify_code');

        $res = true;

        $order->refund_verify = 1;

        $update = $order->save();

        if ($res && $update) {
            return response()->json(['message' => trans('api.validate_succeed'), 'code' => 1, 'status' => true, 'data' => ''], 200);
        } else {
            return response()->json(['message' => trans('api.validate_failed'), 'code' => 0, 'status' => false], 200);
        }
    }

    public function userDistance(OrdersRequest $request)
    {
        $id = $request->get('id');

        $order = Order::where('id', $id)->first();

        $this->authorize('update', $order);#判断用户是否有修改该订单的权限

        //判断订单是否关闭
        if ($order->closed) {
            $this->response->error(trans('api.order_closed'), 200);
        }

        $order->user_distance = $request->get('distance', null);

        $res = $order->save();

        if ($res) {
            return response()->json(['message' => trans('api.save_succeed'), 'code' => 1, 'status' => true, 'data' => ''], 200);
        } else {
            return response()->json(['message' => trans('api.save_failed'), 'code' => 0, 'status' => false], 200);
        }

    }

    public function sellerDistance(OrdersRequest $request)
    {
        $id = $request->get('id');

        $order = Order::where('id', $id)->first();

        $this->authorize('seller_update', $order);#判断用户是否有修改该订单的权限

        //判断订单是否关闭
        if ($order->closed) {
            $this->response->error(trans('api.order_closed'), 200);
        }

        $order->seller_distance = $request->get('distance', null);

        $res = $order->save();

        if ($res) {
            return response()->json(['message' => trans('api.save_succeed'), 'code' => 1, 'status' => true, 'data' => ''], 200);
        } else {
            return response()->json(['message' => trans('api.save_failed'), 'code' => 0, 'status' => false], 200);
        }

    }
}
